/*
 * patchrom.c - C64 ROM patcher.
 *
 * Written by
 *  Peter Weighill <stuce@csv.warwick.ac.uk>
 *  Jouko Valta <jopi@stekt.oulu.fi>
 *
 * Patches by
 *  Marko Makela <msmakela@nic.funet.fi>
 *
 * This file is part of VICE, the Versatile Commodore Emulator.
 * See README for copyright notice.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 *  02111-1307  USA.
 *
 */

#include "vice.h"

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif

#include "log.h"
#include "c64-resources.h"
#include "c64memrom.h"
#include "c64rom.h"
#include "patchrom.h"
#include "types.h"

/*
 * By an option on the x64 command line you can patch between the
 * different roms.
 *
 *   x64 -kernalrev 1           KERNAL ROM R1
 *   x64 -kernalrev 2           KERNAL ROM R2
 *   x64 -kernalrev 3           KERNAL ROM R3
 *   x64 -kernalrev 67          SX-64 or DX-64
 *   x64 -kernalrev sx          SX-64 or DX-64
 *   x64 -kernalrev 100         PET 64 aka 4064 aka Educator 64
 *   x64 -kernalrev 4064        PET 64 aka 4064 aka Educator 64
 */

/*
 * Table of differences between the two versions of the C64 Kernel ROM.
 * To use your national patches, just add the data following
 * the format used below. (Note: Each block must contain data for
 * each patch version.)
 */

#define PATCH_VERSIONS 4   /* counting from 0 */

#define PATCH_901227_01       0
#define PATCH_901227_02       1
#define PATCH_901227_03       2
#define PATCH_SX_251104_04    3
#define PATCH_4064_901246_01  4

static const unsigned short patch_bytes[] = {
    2, 0xE119,
        0xc9, 0xff,
        0xad, 0xe4,
        0xad, 0xe4,
        0xad, 0xe4,
        0xad, 0xe4,

    3, 0xE42D,
        0x20, 0x1E, 0xAB,
        0x20, 0x1E, 0xAB,
        0x20, 0x1E, 0xAB,
        0x20, 0x1E, 0xAB,
        0x4C, 0x41, 0xE4,

    54, 0xE477, /* startup message */
        0x20, 0x20, 0x2A, 0x2A, 0x2A, 0x2A, 0x20, 0x43, 0x4F, 0x4D,
        0x4D, 0x4F, 0x44, 0x4F, 0x52, 0x45, 0x20, 0x36, 0x34, 0x20,
        0x42, 0x41, 0x53, 0x49, 0x43, 0x20, 0x56, 0x32, 0x20, 0x2A,
        0x2A, 0x2A, 0x2A, 0x0D, 0x0D, 0x20, 0x36, 0x34, 0x4B, 0x20,
        0x52, 0x41, 0x4D, 0x20, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4D,
        0x20, 0x20, 0x00, 0x2B,

        0x20, 0x20, 0x2A, 0x2A, 0x2A, 0x2A, 0x20, 0x43, 0x4F, 0x4D,
        0x4D, 0x4F, 0x44, 0x4F, 0x52, 0x45, 0x20, 0x36, 0x34, 0x20,
        0x42, 0x41, 0x53, 0x49, 0x43, 0x20, 0x56, 0x32, 0x20, 0x2A,
        0x2A, 0x2A, 0x2A, 0x0D, 0x0D, 0x20, 0x36, 0x34, 0x4B, 0x20,
        0x52, 0x41, 0x4D, 0x20, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4D,
        0x20, 0x20, 0x00, 0x5C,

        0x20, 0x20, 0x2A, 0x2A, 0x2A, 0x2A, 0x20, 0x43, 0x4F, 0x4D,
        0x4D, 0x4F, 0x44, 0x4F, 0x52, 0x45, 0x20, 0x36, 0x34, 0x20,
        0x42, 0x41, 0x53, 0x49, 0x43, 0x20, 0x56, 0x32, 0x20, 0x2A,
        0x2A, 0x2A, 0x2A, 0x0D, 0x0D, 0x20, 0x36, 0x34, 0x4B, 0x20,
        0x52, 0x41, 0x4D, 0x20, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4D,
        0x20, 0x20, 0x00, 0x81,

        0x20, 0x20, 0x20, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x20, 0x20,
        0x53, 0x58, 0x2D, 0x36, 0x34, 0x20, 0x42, 0x41, 0x53, 0x49,
        0x43, 0x20, 0x56, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x2A, 0x2A,
        0x2A, 0x2A, 0x2A, 0x0D, 0x0D, 0x20, 0x36, 0x34, 0x4B, 0x20,
        0x52, 0x41, 0x4D, 0x20, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4D,
        0x20, 0x20, 0x00, 0xB3,

        0x2A, 0x2A, 0x2A, 0x2A, 0x20, 0x43, 0x4F, 0x4D, 0x4D, 0x4F,
        0x44, 0x4F, 0x52, 0x45, 0x20, 0x34, 0x30, 0x36, 0x34, 0x20,
        0x20, 0x42, 0x41, 0x53, 0x49, 0x43, 0x20, 0x56, 0x32, 0x2E,
        0x30, 0x20, 0x2A, 0x2A, 0x2A, 0x2A, 0x0D, 0x0D, 0x00, 0x20,
        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
        0x20, 0x20, 0x20, 0x63,

    10, 0xE4AD,
        0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
        0x48, 0x20, 0xc9, 0xff, 0xaa, 0x68, 0x90, 0x01, 0x8a, 0x60,
        0x48, 0x20, 0xc9, 0xff, 0xaa, 0x68, 0x90, 0x01, 0x8a, 0x60,
        0x48, 0x20, 0xc9, 0xff, 0xaa, 0x68, 0x90, 0x01, 0x8a, 0x60,
        0x48, 0x20, 0xc9, 0xff, 0xaa, 0x68, 0x90, 0x01, 0x8a, 0x60,

    21, 0xE4C8,
        0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
        0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,

        0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
        0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAD, 0x21, 0xD0,

        0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
        0xAA, 0x85, 0xA9, 0xA9, 0x01, 0x85, 0xAB, 0x60, 0xAD, 0x86, 0x02,

        0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
        0xAA, 0x85, 0xA9, 0xA9, 0x01, 0x85, 0xAB, 0x60, 0xAD, 0x86, 0x02,

        0x2C, 0x86, 0x02, 0x30, 0x0A, 0xA9, 0x00, 0xA2, 0x0E, 0x9D,
        0x20, 0xD0, 0xCA, 0x10, 0xFA, 0x4C, 0x87, 0xEA, 0xAD, 0x21, 0xD0,

    35, 0xE4DD,
        0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
        0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
        0xaa, 0xaa, 0xaa,

        0x91, 0xF3, 0x60, 0x69, 0x02, 0xA4, 0x91, 0xC8, 0xD0, 0x04, 0xC5, 0xA1, 0xD0, 0xF7, 0x60, 0x19,
        0x26, 0x44, 0x19, 0x1A, 0x11, 0xE8, 0x0D, 0x70, 0x0C, 0x06, 0x06, 0xD1, 0x02, 0x37, 0x01, 0xAE,
        0x00, 0x69, 0x00,

        0x91, 0xF3, 0x60, 0x69, 0x02, 0xA4, 0x91, 0xC8, 0xD0, 0x04, 0xC5, 0xA1, 0xD0, 0xF7, 0x60, 0x19,
        0x26, 0x44, 0x19, 0x1A, 0x11, 0xE8, 0x0D, 0x70, 0x0C, 0x06, 0x06, 0xD1, 0x02, 0x37, 0x01, 0xAE,
        0x00, 0x69, 0x00,

        0x91, 0xF3, 0x60, 0x69, 0x02, 0xA4, 0x91, 0xC8, 0xD0, 0x04, 0xC5, 0xA1, 0xD0, 0xF7, 0x60, 0x19,
        0x26, 0x44, 0x19, 0x1A, 0x11, 0xE8, 0x0D, 0x70, 0x0C, 0x06, 0x06, 0xD1, 0x02, 0x37, 0x01, 0xAE,
        0x00, 0x69, 0x00,

        0x91, 0xF3, 0x60, 0x69, 0x02, 0xA4, 0x91, 0xC8, 0xD0, 0x04, 0xC5, 0xA1, 0xD0, 0xF7, 0x60, 0x19,
        0x26, 0x44, 0x19, 0x1A, 0x11, 0xE8, 0x0D, 0x70, 0x0C, 0x06, 0x06, 0xD1, 0x02, 0x37, 0x01, 0xAE,
        0x00, 0x69, 0x00,

    1, 0xE535,
        0x0E,
        0x0E,
        0x0E,
        0x06,
        0x01,

    30, 0xE57C,
        0xB5, 0xD9, 0x29, 0x03, 0x0D, 0x88, 0x02, 0x85, 0xD2, 0xBD,
        0xF0, 0xEC, 0x85, 0xD1, 0xA9, 0x27, 0xE8, 0xB4, 0xD9, 0x30,
        0x06, 0x18, 0x69, 0x28, 0xE8, 0x10, 0xF6, 0x85, 0xD5, 0x60,

        0xB5, 0xD9, 0x29, 0x03, 0x0D, 0x88, 0x02, 0x85, 0xD2, 0xBD,
        0xF0, 0xEC, 0x85, 0xD1, 0xA9, 0x27, 0xE8, 0xB4, 0xD9, 0x30,
        0x06, 0x18, 0x69, 0x28, 0xE8, 0x10, 0xF6, 0x85, 0xD5, 0x60,

        0x20, 0xF0, 0xE9, 0xA9, 0x27, 0xE8, 0xB4, 0xD9, 0x30, 0x06,
        0x18, 0x69, 0x28, 0xE8, 0x10, 0xF6, 0x85, 0xD5, 0x4C, 0x24,
        0xEA, 0xE4, 0xC9, 0xF0, 0x03, 0x4C, 0xED, 0xE6, 0x60, 0xEA,

        0x20, 0xF0, 0xE9, 0xA9, 0x27, 0xE8, 0xB4, 0xD9, 0x30, 0x06,
        0x18, 0x69, 0x28, 0xE8, 0x10, 0xF6, 0x85, 0xD5, 0x4C, 0x24,
        0xEA, 0xE4, 0xC9, 0xF0, 0x03, 0x4C, 0xED, 0xE6, 0x60, 0xEA,

        0x20, 0xF0, 0xE9, 0xA9, 0x27, 0xE8, 0xB4, 0xD9, 0x30, 0x06,
        0x18, 0x69, 0x28, 0xE8, 0x10, 0xF6, 0x85, 0xD5, 0x4C, 0x24,
        0xEA, 0xE4, 0xC9, 0xF0, 0x03, 0x4C, 0xED, 0xE6, 0x60, 0xEA,

    1, 0xE5EF,
        0x09,
        0x09,
        0x09,
        0x0F,
        0x09,

    2, 0xE5F4,
        0xE6, 0xEC,
        0xE6, 0xEC,
        0xE6, 0xEC,
        0xD7, 0xF0,
        0xE6, 0xEC,

    2, 0xE622,
        0xED, 0xE6,
        0xED, 0xE6,
        0x91, 0xE5,
        0x91, 0xE5,
        0x91, 0xE5,

    12, 0xEA07,
        0xA9, 0x20, 0x91, 0xD1, 0xa9, 0x01, 0x91, 0xf3, 0x88, 0x10,
        0xF5, 0x60,
        0xA9, 0x20, 0x91, 0xD1, 0x20, 0xDA, 0xE4, 0xEA, 0x88, 0x10,
        0xF5, 0x60,
        0x20, 0xDA, 0xE4, 0xA9, 0x20, 0x91, 0xD1, 0x88, 0x10, 0xF6,
        0x60, 0xEA,
        0x20, 0xDA, 0xE4, 0xA9, 0x20, 0x91, 0xD1, 0x88, 0x10, 0xF6,
        0x60, 0xEA,
        0xA9, 0x20, 0x91, 0xD1, 0x20, 0xDA, 0xE4, 0xEA, 0x88, 0x10,
        0xF5, 0x60,

    2, 0xEA7C,
        0x87, 0xea,
        0x87, 0xea,
        0x87, 0xea,
        0x87, 0xea,
        0xc8, 0xe4,

    2, 0xECCA,
        0x1b, 0x00,
        0x9b, 0x37,
        0x9b, 0x37,
        0x9b, 0x37,
        0x9b, 0x37,

    1, 0xECD2,
        0x00,
        0x0f,
        0x0f,
        0x0f,
        0x0f,

    14, 0xECD9,
        0x0E, 0x06, 0x01, 0x02, 0x03, 0x04, 0x00, 0x01, 0x02, 0x03,
        0x04, 0x05, 0x06, 0x07,
        0x0E, 0x06, 0x01, 0x02, 0x03, 0x04, 0x00, 0x01, 0x02, 0x03,
        0x04, 0x05, 0x06, 0x07,
        0x0E, 0x06, 0x01, 0x02, 0x03, 0x04, 0x00, 0x01, 0x02, 0x03,
        0x04, 0x05, 0x06, 0x07,
        0x03, 0x01, 0x01, 0x02, 0x03, 0x04, 0x00, 0x01, 0x02, 0x03,
        0x04, 0x05, 0x06, 0x07,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,

    3, 0xEF94,
        0x85, 0xA9, 0x60,
        0x85, 0xA9, 0x60,
        0x4C, 0xD3, 0xE4,
        0x4C, 0xD3, 0xE4,
        0x85, 0xA9, 0x60,

    15, 0xF0D8,
        0x0D, 0x50, 0x52, 0x45, 0x53, 0x53, 0x20, 0x50, 0x4C, 0x41,
        0x59, 0x20, 0x4F, 0x4E, 0x20,
        0x0D, 0x50, 0x52, 0x45, 0x53, 0x53, 0x20, 0x50, 0x4C, 0x41,
        0x59, 0x20, 0x4F, 0x4E, 0x20,
        0x0D, 0x50, 0x52, 0x45, 0x53, 0x53, 0x20, 0x50, 0x4C, 0x41,
        0x59, 0x20, 0x4F, 0x4E, 0x20,
        0x4C, 0x4F, 0x41, 0x44, 0x22, 0x3A, 0x2A, 0x22, 0x2C, 0x38,
        0x0D, 0x52, 0x55, 0x4E, 0x0D,
        0x0D, 0x50, 0x52, 0x45, 0x53, 0x53, 0x20, 0x50, 0x4C, 0x41,
        0x59, 0x20, 0x4F, 0x4E, 0x20,

    1, 0xF387,
        0x03,
        0x03,
        0x03,
        0x08,
        0x03,

   37, 0xF428,
        0xD0, 0x0B, 0xAD, 0x95, 0x02, 0x0A, 0xA8, 0xAD, 0x96, 0x02, 0x4C, 0x3F, 0xF4, 0x0A, 0xAA, 0xBD,
        0xC0, 0xFE, 0x0A, 0xA8, 0xBD, 0xC1, 0xFE, 0x2A, 0x48, 0x98, 0x69, 0xC8, 0x8D, 0x99, 0x02, 0x68,
        0x69, 0x00, 0x8D, 0x9A, 0x02,

        0xF0, 0x1C, 0x0A, 0xAA, 0xAD, 0xA6, 0x02, 0xD0, 0x09, 0xBC, 0xC1, 0xFE, 0xBD, 0xC0, 0xFE, 0x4C,
        0x40, 0xF4, 0xBC, 0xEB, 0xE4, 0xBD, 0xEA, 0xE4, 0x8C, 0x96, 0x02, 0x8D, 0x95, 0x02, 0xAD, 0x95,
        0x02, 0x0A, 0x20, 0x2E, 0xFF,

        0xF0, 0x1C, 0x0A, 0xAA, 0xAD, 0xA6, 0x02, 0xD0, 0x09, 0xBC, 0xC1, 0xFE, 0xBD, 0xC0, 0xFE, 0x4C,
        0x40, 0xF4, 0xBC, 0xEB, 0xE4, 0xBD, 0xEA, 0xE4, 0x8C, 0x96, 0x02, 0x8D, 0x95, 0x02, 0xAD, 0x95,
        0x02, 0x0A, 0x20, 0x2E, 0xFF,

        0xF0, 0x1C, 0x0A, 0xAA, 0xAD, 0xA6, 0x02, 0xD0, 0x09, 0xBC, 0xC1, 0xFE, 0xBD, 0xC0, 0xFE, 0x4C,
        0x40, 0xF4, 0xBC, 0xEB, 0xE4, 0xBD, 0xEA, 0xE4, 0x8C, 0x96, 0x02, 0x8D, 0x95, 0x02, 0xAD, 0x95,
        0x02, 0x0A, 0x20, 0x2E, 0xFF,

        0xF0, 0x1C, 0x0A, 0xAA, 0xAD, 0xA6, 0x02, 0xD0, 0x09, 0xBC, 0xC1, 0xFE, 0xBD, 0xC0, 0xFE, 0x4C,
        0x40, 0xF4, 0xBC, 0xEB, 0xE4, 0xBD, 0xEA, 0xE4, 0x8C, 0x96, 0x02, 0x8D, 0x95, 0x02, 0xAD, 0x95,
        0x02, 0x0A, 0x20, 0x2E, 0xFF,

    1, 0xF459,
        0x4c,
        0x20,
        0x20,
        0x20,
        0x20,

    1, 0xF4B7,
        0x7B,
        0x7B,
        0x7B,
        0xF7,
        0x7B,

    1, 0xF5F9,
        0x5F,
        0x5F,
        0x5F,
        0xF7,
        0x5F,

    5, 0xF762,
        0x91, 0xc9, 0xff, 0xf0, 0xfa,
        0xa1, 0x20, 0xe0, 0xe4, 0xea,
        0xa1, 0x20, 0xe0, 0xe4, 0xea,
        0xa1, 0x20, 0xe0, 0xe4, 0xea,
        0xa1, 0x20, 0xe0, 0xe4, 0xea,

    1, 0xF81F,
        0x2F,
        0x2F,
        0x2F,
        0x2F,
        0x2B,

    1, 0xF82C,
        0x2F,
        0x2F,
        0x2F,
        0x2F,
        0x2B,

    2, 0xFCFC,
        0x18, 0xe5,
        0x5b, 0xff,
        0x5b, 0xff,
        0x5b, 0xff,
        0x5b, 0xff,

    32, 0xFDDD,
        0xA9, 0x1B, 0x8D, 0x04, 0xDC, 0xA9, 0x41, 0x8D, 0x05, 0xDC, 0xA9, 0x81, 0x8D, 0x0D, 0xDC, 0xAD,
        0x0E, 0xDC, 0x29, 0x80, 0x09, 0x11, 0x8D, 0x0E, 0xDC, 0x4C, 0x8E, 0xEE, 0x85, 0xB7, 0x86, 0xBB,

        0xAD, 0xA6, 0x02, 0xF0, 0x0A, 0xA9, 0x25, 0x8D, 0x04, 0xDC, 0xA9, 0x40, 0x4C, 0xF3, 0xFD, 0xA9,
        0x95, 0x8D, 0x04, 0xDC, 0xA9, 0x42, 0x8D, 0x05, 0xDC, 0x4C, 0x6E, 0xFF, 0x85, 0xB7, 0x86, 0xBB,

        0xAD, 0xA6, 0x02, 0xF0, 0x0A, 0xA9, 0x25, 0x8D, 0x04, 0xDC, 0xA9, 0x40, 0x4C, 0xF3, 0xFD, 0xA9,
        0x95, 0x8D, 0x04, 0xDC, 0xA9, 0x42, 0x8D, 0x05, 0xDC, 0x4C, 0x6E, 0xFF, 0x85, 0xB7, 0x86, 0xBB,

        0xAD, 0xA6, 0x02, 0xF0, 0x0A, 0xA9, 0x25, 0x8D, 0x04, 0xDC, 0xA9, 0x40, 0x4C, 0xF3, 0xFD, 0xA9,
        0x95, 0x8D, 0x04, 0xDC, 0xA9, 0x42, 0x8D, 0x05, 0xDC, 0x4C, 0x6E, 0xFF, 0x85, 0xB7, 0x86, 0xBB,

        0xAD, 0xA6, 0x02, 0xF0, 0x0A, 0xA9, 0x25, 0x8D, 0x04, 0xDC, 0xA9, 0x40, 0x4C, 0xF3, 0xFD, 0xA9,
        0x95, 0x8D, 0x04, 0xDC, 0xA9, 0x42, 0x8D, 0x05, 0xDC, 0x4C, 0x6E, 0xFF, 0x85, 0xB7, 0x86, 0xBB,

    19, 0xFEC2,
        0xAC, 0x26, 0xA7, 0x19, 0x5D, 0x11, 0x1F, 0x0E, 0xA1, 0x0C, 0x1F, 0x06, 0xDD, 0x02, 0x3D, 0x01,
        0xB2, 0x00, 0x6C,
        0xC1, 0x27, 0x3E, 0x1A, 0xC5, 0x11, 0x74, 0x0E, 0xED, 0x0C, 0x45, 0x06, 0xF0, 0x02, 0x46, 0x01,
        0xB8, 0x00, 0x71,
        0xC1, 0x27, 0x3E, 0x1A, 0xC5, 0x11, 0x74, 0x0E, 0xED, 0x0C, 0x45, 0x06, 0xF0, 0x02, 0x46, 0x01,
        0xB8, 0x00, 0x71,
        0xC1, 0x27, 0x3E, 0x1A, 0xC5, 0x11, 0x74, 0x0E, 0xED, 0x0C, 0x45, 0x06, 0xF0, 0x02, 0x46, 0x01,
        0xB8, 0x00, 0x71,
        0xC1, 0x27, 0x3E, 0x1A, 0xC5, 0x11, 0x74, 0x0E, 0xED, 0x0C, 0x45, 0x06, 0xF0, 0x02, 0x46, 0x01,
        0xB8, 0x00, 0x71,

    64, 0xFF08,
        0x93, 0x02, 0x29, 0x0F, 0xD0, 0x0C, 0xAD, 0x95, 0x02, 0x8D, 0x06, 0xDD, 0xAD, 0x96, 0x02, 0x4C,
        0x25, 0xFF, 0x0A, 0xAA, 0xBD, 0xC0, 0xFE, 0x8D, 0x06, 0xDD, 0xBD, 0xC1, 0xFE, 0x8D, 0x07, 0xDD,
        0xA9, 0x11, 0x8D, 0x0F, 0xDD, 0xA9, 0x12, 0x4D, 0xA1, 0x02, 0x8D, 0xA1, 0x02, 0xA9, 0xFF, 0x8D,
        0x06, 0xDD, 0x8D, 0x07, 0xDD, 0xAE, 0x98, 0x02, 0x86, 0xA8, 0x60, 0x08, 0x68, 0x29, 0xEF, 0x48,

        0x95, 0x02, 0x8D, 0x06, 0xDD, 0xAD, 0x96, 0x02, 0x8D, 0x07, 0xDD, 0xA9, 0x11, 0x8D, 0x0F, 0xDD,
        0xA9, 0x12, 0x4D, 0xA1, 0x02, 0x8D, 0xA1, 0x02, 0xA9, 0xFF, 0x8D, 0x06, 0xDD, 0x8D, 0x07, 0xDD,
        0xAE, 0x98, 0x02, 0x86, 0xA8, 0x60, 0xAA, 0xAD, 0x96, 0x02, 0x2A, 0xA8, 0x8A, 0x69, 0xC8, 0x8D,
        0x99, 0x02, 0x98, 0x69, 0x00, 0x8D, 0x9A, 0x02, 0x60, 0xEA, 0xEA, 0x08, 0x68, 0x29, 0xEF, 0x48,

        0x95, 0x02, 0x8D, 0x06, 0xDD, 0xAD, 0x96, 0x02, 0x8D, 0x07, 0xDD, 0xA9, 0x11, 0x8D, 0x0F, 0xDD,
        0xA9, 0x12, 0x4D, 0xA1, 0x02, 0x8D, 0xA1, 0x02, 0xA9, 0xFF, 0x8D, 0x06, 0xDD, 0x8D, 0x07, 0xDD,
        0xAE, 0x98, 0x02, 0x86, 0xA8, 0x60, 0xAA, 0xAD, 0x96, 0x02, 0x2A, 0xA8, 0x8A, 0x69, 0xC8, 0x8D,
        0x99, 0x02, 0x98, 0x69, 0x00, 0x8D, 0x9A, 0x02, 0x60, 0xEA, 0xEA, 0x08, 0x68, 0x29, 0xEF, 0x48,

        0x95, 0x02, 0x8D, 0x06, 0xDD, 0xAD, 0x96, 0x02, 0x8D, 0x07, 0xDD, 0xA9, 0x11, 0x8D, 0x0F, 0xDD,
        0xA9, 0x12, 0x4D, 0xA1, 0x02, 0x8D, 0xA1, 0x02, 0xA9, 0xFF, 0x8D, 0x06, 0xDD, 0x8D, 0x07, 0xDD,
        0xAE, 0x98, 0x02, 0x86, 0xA8, 0x60, 0xAA, 0xAD, 0x96, 0x02, 0x2A, 0xA8, 0x8A, 0x69, 0xC8, 0x8D,
        0x99, 0x02, 0x98, 0x69, 0x00, 0x8D, 0x9A, 0x02, 0x60, 0xEA, 0xEA, 0x08, 0x68, 0x29, 0xEF, 0x48,

        0x95, 0x02, 0x8D, 0x06, 0xDD, 0xAD, 0x96, 0x02, 0x8D, 0x07, 0xDD, 0xA9, 0x11, 0x8D, 0x0F, 0xDD,
        0xA9, 0x12, 0x4D, 0xA1, 0x02, 0x8D, 0xA1, 0x02, 0xA9, 0xFF, 0x8D, 0x06, 0xDD, 0x8D, 0x07, 0xDD,
        0xAE, 0x98, 0x02, 0x86, 0xA8, 0x60, 0xAA, 0xAD, 0x96, 0x02, 0x2A, 0xA8, 0x8A, 0x69, 0xC8, 0x8D,
        0x99, 0x02, 0x98, 0x69, 0x00, 0x8D, 0x9A, 0x02, 0x60, 0xEA, 0xEA, 0x08, 0x68, 0x29, 0xEF, 0x48,

    38, 0xFF5B,
        0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
        0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
        0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,

        0x20, 0x18, 0xE5, 0xAD, 0x12, 0xD0, 0xD0, 0xFB, 0xAD, 0x19, 0xD0, 0x29, 0x01, 0x8D, 0xA6, 0x02,
        0x4C, 0xDD, 0xFD, 0xA9, 0x81, 0x8D, 0x0D, 0xDC, 0xAD, 0x0E, 0xDC, 0x29, 0x80, 0x09, 0x11, 0x8D,
        0x0E, 0xDC, 0x4C, 0x8E, 0xEE, 0x00,

        0x20, 0x18, 0xE5, 0xAD, 0x12, 0xD0, 0xD0, 0xFB, 0xAD, 0x19, 0xD0, 0x29, 0x01, 0x8D, 0xA6, 0x02,
        0x4C, 0xDD, 0xFD, 0xA9, 0x81, 0x8D, 0x0D, 0xDC, 0xAD, 0x0E, 0xDC, 0x29, 0x80, 0x09, 0x11, 0x8D,
        0x0E, 0xDC, 0x4C, 0x8E, 0xEE, 0x00,

        0x20, 0x18, 0xE5, 0xAD, 0x12, 0xD0, 0xD0, 0xFB, 0xAD, 0x19, 0xD0, 0x29, 0x01, 0x8D, 0xA6, 0x02,
        0x4C, 0xDD, 0xFD, 0xA9, 0x81, 0x8D, 0x0D, 0xDC, 0xAD, 0x0E, 0xDC, 0x29, 0x80, 0x09, 0x11, 0x8D,
        0x0E, 0xDC, 0x4C, 0x8E, 0xEE, 0x00,

        0x20, 0x18, 0xE5, 0xAD, 0x12, 0xD0, 0xD0, 0xFB, 0xAD, 0x19, 0xD0, 0x29, 0x01, 0x8D, 0xA6, 0x02,
        0x4C, 0xDD, 0xFD, 0xA9, 0x81, 0x8D, 0x0D, 0xDC, 0xAD, 0x0E, 0xDC, 0x29, 0x80, 0x09, 0x11, 0x8D,
        0x0E, 0xDC, 0x4C, 0x8E, 0xEE, 0x00,

    1, 0xFF80,    /* The version ID byte */
        0xaa,
        0x00,
        0x03,
        0x43,
        0x64,

    2, 0xFF82,
        0x18, 0xe5,
        0x5b, 0xff,
        0x5b, 0xff,
        0x5b, 0xff,
        0x5b, 0xff,

    2, 0xFFF8,
        0x42, 0x59,
        0x42, 0x59,
        0x42, 0x59,
        0x42, 0x59,
        0x00, 0x00,

    0, 00
};

int patch_rom_idx(int rev)
{
    uint16_t sum;                   /* ROM checksum */
    int curr, num;
    short bytes, n, i = 0;
    uint16_t a;

    if (c64rom_get_kernal_chksum_id(&sum, &curr) < 0) {
        log_error(LOG_DEFAULT, "ROM not patched: Unknown Kernal image.  ID: %d ($%02X) Sum: %d ($%04X).", curr, curr, sum, sum);
        return -1;
    }
    log_verbose("Trying Kernal ROM patch: id:%d/sum:%d to id:%d.", curr, sum, rev);

    if (rev == curr) {
        log_verbose("ROM not patched: Already revision #%d.", curr);
        return 0;
    }
    if (rev < 0) {
        log_error(LOG_DEFAULT, "ROM not patched: Unknown ID: %d ($%02X).", rev, rev);
        return -1;
    }

    /* create index */

    num = rev;

    switch (rev) {
        case C64_KERNAL_4064:
            rev = PATCH_4064_901246_01; /* index for rev100 data */
            break;
        case C64_KERNAL_SX64:
            rev = PATCH_SX_251104_04; /* index for rev67 data */
            break;
        case C64_KERNAL_REV3:
            rev = PATCH_901227_03; /* index for rev03 data */
            break;
        case C64_KERNAL_REV2:
            rev = PATCH_901227_02;
            break;
        case C64_KERNAL_REV1:
            rev = PATCH_901227_01;
            break;
        default:
            log_error(LOG_DEFAULT, "Cannot patch ROM to revision #%d.", rev);
            return -1;
    }

    log_message(LOG_DEFAULT, "Installing ROM patch for revision #%d:", num);

    i = 0;
    while ((bytes = patch_bytes[i++]) > 0) {
        a = (uint16_t)patch_bytes[i++];

        log_verbose("  %.4X (%d byte%s)", a & 0xFFFF, bytes, ((bytes > 1) ? "s" : ""));

        i += (bytes * rev);     /* select patch */
        for (n = bytes; n--; ) {
            c64memrom_rom64_store(a++, (uint8_t)patch_bytes[i++]);
        }

        i += (bytes * (PATCH_VERSIONS - rev));  /* skip patch */
    }
    return 0;
}
